
import { $, component$, useOnWindow, useSignal } from "@builder.io/qwik"
import { ResizeMode, type ResizeProps } from "./types";

const Resizer = component$<ResizeProps>((props) => {
    const {
        onMaxHeight,
        onMaxWidth,
        onMinHeight,
        onMinWidth,
        onResizeStart,
        onResize,
        onResizeEnd,
        mode = ResizeMode.Right,
        className,
        style,
    } = props;

    const position = useSignal<{ x: number, y: number }>({ x: 0, y: 0 });
    const isDragging = useSignal<boolean>(false);
    const dragLine = useSignal<HTMLDivElement>();

    const onDragLineStart = $((e: MouseEvent) => {
        isDragging.value = true;
        onResizeStart && onResizeStart(e);
        const { clientX, clientY } = e;
        position.value = { x: clientX, y: clientY };
    })

    const onDragLineMove = $((e: MouseEvent) => {
        if (!isDragging.value) return
        const parentNode = dragLine.value?.parentNode as HTMLElement;
        parentNode.style.transition = 'none';
        const { clientX, clientY } = e;
        const { x, y } = position.value;
        const { maxWidth, maxHeight, minWidth, minHeight } = props;
        const nSize: { width?: number, height?: number } = {};
        // 左/右/上左/上右/下左/下右 时改变宽度
        if ([
            ResizeMode.Left,
            ResizeMode.Right,
            ResizeMode.LeftTop,
            ResizeMode.LeftBottom,
            ResizeMode.RightTop,
            ResizeMode.RightBottom
        ].includes(mode)) {
            // 计算宽度
            const deltaX = (clientX - x) * ([ResizeMode.Left, ResizeMode.LeftTop, ResizeMode.LeftBottom].includes(mode) ? -1 : 1);
            const offWidth = parentNode.offsetWidth;
            let newWidth = offWidth + deltaX;
            if (maxWidth && newWidth > maxWidth) {
                newWidth = maxWidth;
                onMaxWidth && onMaxWidth(e, maxWidth);
            }
            if (minWidth && newWidth < minWidth) {
                newWidth = minWidth;
                onMinWidth && onMinWidth(e, minWidth);
            }
            nSize.width = newWidth;
            parentNode.style.width = `${newWidth}px`;
        }
        // 上/下/上左/上右/下左/下右 时改变高度
        if ([
            ResizeMode.Top,
            ResizeMode.Bottom,
            ResizeMode.LeftTop,
            ResizeMode.LeftBottom,
            ResizeMode.RightTop,
            ResizeMode.RightBottom
        ].includes(mode)) {
            // 计算高度
            const deltaY = (clientY - y) * ([ResizeMode.Top, ResizeMode.LeftTop, ResizeMode.RightTop].includes(mode) ? -1 : 1);
            const offHeight = parentNode.offsetHeight;
            let newHeight = offHeight + deltaY;
            if (maxHeight && newHeight > maxHeight) {
                newHeight = maxHeight;
                onMaxHeight && onMaxHeight(e, maxHeight);
            }
            if (minHeight && newHeight < minHeight) {
                newHeight = minHeight;
                onMinHeight && onMinHeight(e, minHeight);
            }
            parentNode.style.height = `${newHeight}px`;
            nSize.height = newHeight;
        }
        onResize && onResize(e, nSize);
        position.value = { x: clientX, y: clientY };
    })

    const onDragLineEnd = $((e: MouseEvent) => {
        if (!isDragging.value) return
        onResizeEnd && onResizeEnd(e);
        isDragging.value = false
        const parentNode = dragLine.value?.parentNode as HTMLElement;
        parentNode.style.transition = '';
    })
    useOnWindow('mousemove', onDragLineMove);
    useOnWindow('mouseup', onDragLineEnd);
    // 处理拖拽事件
    return <div ref={dragLine}
        style={style}
        onMouseDown$={onDragLineStart}
        class={[
            "resize-line transition-colors duration-200 ease-linear hover:bg-qrui-primary-base-color absolute",
            {
                "w-[4px] h-full left-0 top-0 cursor-ew-resize": mode === ResizeMode.Left,
                "w-[4px] h-full right-0 top-0 cursor-ew-resize": mode === ResizeMode.Right,
                "w-full h-[4px] left-0 top-0 cursor-ns-resize": mode === ResizeMode.Top,
                "w-full h-[4px] left-0 bottom-0 cursor-ns-resize": mode === ResizeMode.Bottom,
                "w-[4px] h-[4px] left-0 top-0 cursor-nw-resize": mode === ResizeMode.LeftTop,
                "w-[4px] h-[4px] right-0 top-0 cursor-ne-resize": mode === ResizeMode.RightTop,
                "w-[4px] h-[4px] left-0 bottom-0 cursor-sw-resize": mode === ResizeMode.LeftBottom,
                "w-[4px] h-[4px] right-0 bottom-0 cursor-se-resize": mode === ResizeMode.RightBottom,
            },
            className
        ]} />
})

export default Resizer;